package com.example.testsbjenkins.zip;

import java.io.*;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * @author: lt
 * @date: 2022/6/24 10:44
 * @Description: todo
 */
public class ZipUtil {

    /**
     * 压缩单个文件
     * @throws IOException
     */
    static void zipFile() throws IOException {

        //输出压缩包
        FileOutputStream out = new FileOutputStream("C:\\Users\\Administrator.DESKTOP-4PCK80Q\\Desktop\\test\\zip\\compose.zip");
        ZipOutputStream zipOutputStream = new ZipOutputStream(out);
        
        //被压缩文件
        File fileToZip = new File("C:\\Users\\Administrator.DESKTOP-4PCK80Q\\Desktop\\test\\1.txt");
        FileInputStream in = new FileInputStream(fileToZip);
        
        //向压缩包中添加文件
        ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
        zipOutputStream.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = in.read(bytes))!=-1){
            zipOutputStream.write(bytes,0,length);
        }
        zipOutputStream.close();
        in.close();
        out.close();

    }


    /**
     * 压缩多个文件
     * @throws IOException
     */
    static void zipMultiesFile() throws IOException {

        List<String> fileUrls = Arrays.asList("C:\\Users\\Administrator.DESKTOP-4PCK80Q\\Desktop\\test\\1.txt", "C:\\Users\\Administrator.DESKTOP-4PCK80Q\\Desktop\\test\\2.txt");
        //输出压缩包
        FileOutputStream out = new FileOutputStream("C:\\Users\\Administrator.DESKTOP-4PCK80Q\\Desktop\\test\\zip\\multicompose.zip");
        ZipOutputStream zipOutputStream = new ZipOutputStream(out);

        for (String url : fileUrls) {
            File fileToZip = new File(url);
            FileInputStream in = new FileInputStream(fileToZip);
            ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
            zipOutputStream.putNextEntry(zipEntry);
            byte[] bytes = new byte[1024];
            int length;
            while ((length = in.read(bytes))!=-1){
                zipOutputStream.write(bytes,0,length);
            }
            in.close();
        }
        zipOutputStream.close();
        out.close();
    }

    
    static void zipDir() throws IOException {

        //被压缩的文件夹
        String sourceDir = "C:\\Users\\Administrator.DESKTOP-4PCK80Q\\Desktop\\test\\testDir";

        //输出压缩包
        FileOutputStream out = new FileOutputStream("C:\\Users\\Administrator.DESKTOP-4PCK80Q\\Desktop\\test\\zip\\dircompose.zip");
        ZipOutputStream zipOutputStream = new ZipOutputStream(out);
        File dirToZip = new File(sourceDir);
        //递归压缩文件夹
        zipFile(dirToZip, dirToZip.getName(), zipOutputStream);
        zipOutputStream.close();
        out.close();
        
        
    }

    /**
     * 将dirToZip文件夹及其子目录文件递归压缩到zip文件中
     * @param dirToZip 递归当前处理对象，可能是文件夹，也可能是文件
     * @param fileName dirToZip文件或文件夹名称
     * @param zipOutputStream 压缩文件输出流
     */
    private static void zipFile(File dirToZip, String fileName, ZipOutputStream zipOutputStream) throws IOException {

        //不压缩隐藏文件夹
        if (dirToZip.isHidden()) {
            return;
        }
        //判断压缩对象是一个文件夹
        if (dirToZip.isDirectory()) {

            if (fileName.endsWith("/")) {
                //如果文件夹是以“/”结尾，将文件夹作为压缩箱放入zipOut压缩输出流
                zipOutputStream.putNextEntry(new ZipEntry(fileName));
                zipOutputStream.close();
            }else {
                //如果文件夹不是以“/”结尾，将文件夹结尾加上“/”之后作为压缩箱放入zipOut压缩输出流
                zipOutputStream.putNextEntry(new ZipEntry(fileName + "/"));
                zipOutputStream.closeEntry();
                
            }

            //遍历文件夹子目录，进行递归的zipFile
            File[] children  = dirToZip.listFiles();
            for (File child : children) {
                zipFile(child,fileName+"/"+child.getName(),zipOutputStream);
            }
            //如果当前递归对象是文件夹，加入ZipEntry之后就返回
            return;
        }
        
        //如果当前的fileToZip不是一个文件夹，是一个文件，将其以字节码形式压缩到压缩包里面
        FileInputStream fis = new FileInputStream(dirToZip);
        ZipEntry zipEntry = new ZipEntry(fileName);
        zipOutputStream.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zipOutputStream.write(bytes, 0, length);
        }
        fis.close();

    }


    /**
     * 解压 
     * @param zipFilePath  需要解压的压缩包
     * @param desDirectory 解压后的目标目录
     * @throws Exception
     */
    public static void unzip(String zipFilePath, String desDirectory) throws Exception {

        File desDir = new File(desDirectory);
        if (!desDir.exists()) {
            boolean mkdirSuccess = desDir.mkdir();
            if (!mkdirSuccess) {
                throw new Exception("创建解压目标文件夹失败");
            }
        }
        // 读入流
        ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath));
        // 遍历每一个文件
        ZipEntry zipEntry = zipInputStream.getNextEntry();
        while (zipEntry != null) {
            if (zipEntry.isDirectory()) { // 文件夹
                String unzipFilePath = desDirectory + File.separator + zipEntry.getName();
                // 直接创建
                mkdir(new File(unzipFilePath));
            } else { // 文件
                String unzipFilePath = desDirectory + File.separator + zipEntry.getName();
                File file = new File(unzipFilePath);
                // 创建父目录
                mkdir(file.getParentFile());
                // 写出文件流
                BufferedOutputStream bufferedOutputStream =
                        new BufferedOutputStream(new FileOutputStream(unzipFilePath));
                byte[] bytes = new byte[1024];
                int readLen;
                while ((readLen = zipInputStream.read(bytes)) != -1) {
                    bufferedOutputStream.write(bytes, 0, readLen);
                }
                bufferedOutputStream.close();
            }
            zipInputStream.closeEntry();
            zipEntry = zipInputStream.getNextEntry();
        }
        zipInputStream.close();
    }

    // 如果父目录不存在则创建
    private static void mkdir(File file) {
        if (null == file || file.exists()) {
            return;
        }
        mkdir(file.getParentFile());
        file.mkdir();
    }

    

    public static void main(String[] args) throws Exception {
        //zipFile();
        //    zipMultiesFile();
        //zipDir();
        //unZipFile();
        String sourceFile = "C:\\Users\\Administrator.DESKTOP-4PCK80Q\\Desktop\\test\\zip\\dircompose.zip";
        //解压后的目标目录
        String destDirStr = "C:\\Users\\Administrator.DESKTOP-4PCK80Q\\Desktop\\test\\unzipTest";
        unzip(sourceFile,destDirStr);
    }
    
}
